// Copyright (C) 2023 Toitware ApS.
// Use of this source code is governed by a Zero-Clause BSD license that can
// be found in the tests/LICENSE file.

import expect show *

import core
import crypto show *
import crypto.adler32 show *
import crypto.aes show *
import crypto.blake2 show *
import crypto.chacha20 show *
import crypto.sha show *
import crypto.siphash show *
import crypto.sha1 show *
import crypto.crc show *
import crypto.md5 show *
import crypto.hamming
import crypto.hmac show *
import tls.session show tls-get-random_

import encoding.hex
import encoding.base64
import io show BIG-ENDIAN

import .confuse
import .io-utils

expect name [code]:
  expect-equals
    name
    catch code

expect-out-of-range [code]:
  expect "OUT_OF_RANGE" code

expect-invalid-argument [code]:
  expect "INVALID_ARGUMENT" code

expect-integer-parsing-error [code]:
  expect "INTEGER_PARSING_ERROR" code

expect-already-closed [code]:
  expect "ALREADY_CLOSED" code

expect-equal-arrays a b:
  expect-equals a.size b.size
  a.size.repeat:
    expect-equals a[it] b[it]

main:
  hex-test
  hamming-test
  hash-test
  chacha-test
  sip-test
  aead-simple-test
  adler-test
  blake-test
  md5-test
  hmac-test
  random-test

hex-test -> none:
  expect-equals "" (hex.encode #[])
  expect-equals "" (hex.encode "")
  expect-equals "a5" (hex.encode #[0xa5])
  expect-equals "41" (hex.encode "A")

  expect-equals "a552" (hex.encode #[0xa5, 0x52])
  expect-equals "4134" (hex.encode "A4")
  expect-equals "c3b8" (hex.encode "ø")

  expect-equals #[] (hex.decode "")
  expect-equals #[0xa5] (hex.decode "a5")
  expect-equals #[0xa5] (hex.decode "A5")
  expect-equals #[0x41] (hex.decode "41")

  expect-equals #[0xf5, 0x52] (hex.decode "f552")
  expect-equals #[0xf5, 0x52] (hex.decode "F552")
  expect-equals #[0x41, 0x34] (hex.decode "4134")

  expect-equals #[10] (hex.decode "a")
  expect-integer-parsing-error: hex.decode "s"
  expect-integer-parsing-error: hex.decode "sa"
  expect-integer-parsing-error: hex.decode "as"
  expect-invalid-argument: hex.decode "0348af8g1921"
  expect-invalid-argument: hex.decode "-348af8a1921"

hash-test -> none:
  EMPTY-HEX ::= "da39a3ee5e6b4b0d3255bfef95601890afd80709"
  EMPTY-SHA224 ::= "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
  EMPTY-SHA2 ::= "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
  EMPTY-SHA384 ::= "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"
  EMPTY-SHA512 ::= "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
  EMPTY-CRC32 ::=  "00000000"
  EMPTY-CRC16 ::=  "0000"
  expect-equals EMPTY-HEX (hex.encode (sha1 ""))
  expect-equals EMPTY-SHA224 (hex.encode (sha224 ""))
  expect-equals EMPTY-SHA2 (hex.encode (sha256 ""))
  expect-equals EMPTY-SHA384 (hex.encode (sha384 ""))
  expect-equals EMPTY-SHA512 (hex.encode (sha512 ""))
  expect-equals 0 (crc16-xmodem "")
  expect-equals 0 (crc32 "")
  expect-equals "2jmj7l5rSw0yVb/vlWAYkK/YBwk=" (base64.encode (sha1 ""))

  PARTY ::= "Now is the time for all good men to come to the aid of the party"
  hash := sha1 PARTY
  expect-equals "02d2837a5cc31aa9feb8f66a2a3db9819464542b" (hex.encode hash)
  hash2 := sha256 PARTY
  hash3 := crc32 PARTY
  hash4 := crc16-xmodem PARTY
  hash5 := sha224 PARTY
  hash6 := sha384 PARTY
  hash7 := sha512 PARTY
  expect-equals "f160938592eeac116451ebc4da23dbc17e29283aef99de0197d705ad4d4c43f1" (hex.encode hash2)
  expect-equals "d0302485" "$(%x hash3)"
  expect-equals "7ea8" "$(%x hash4)"
  expect-equals "AtKDelzDGqn+uPZqKj25gZRkVCs=" (base64.encode hash)
  expect-equals "0824c514a92fcac7cbe5221d1d28d7e0cfb061d4dbb33f0a8f1fe9c2" (hex.encode hash5)
  expect-equals "77d1a7ca704cd324b3519f2d89f455953e25801373bfc5a9eea38d16bc1aa57f1c90f0250c7bab60b07622c9bad5c1bf" (hex.encode hash6)
  expect-equals "f8777873ec6d5108191afeccc87c696fea78dcdf156a420bf3efadb1669d0adf56a2139ca7da2b8511e1ac25a9ce230dc0a7fe7a721e2ebcb7f8182f41dcc162" (hex.encode hash7)

  expect-equals EMPTY-HEX (hex.encode (sha1 ""))
  expect-equal-arrays (sha1 (ByteArray 0)) (sha1 "")
  expect-equal-arrays (sha256 (ByteArray 0)) (sha256 "")

  expect-equals "0a0a9f2a6772942557ab5355d76af442f8f65e01" (hex.encode (sha1 "Hello, World!"))
  expect-equals "dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f" (hex.encode (sha256 "Hello, World!"))
  expect-equal-arrays (sha1 ("Hello, World!".to-byte-array)) (sha1 "Hello, World!")

  sha1 := Sha1
  sha1-io-data := Sha1
  sha2 := Sha256
  sha2-io-data := Sha256
  crc32 := Crc32
  crc16 := Crc16Xmodem
  expect-equals EMPTY-HEX (hex.encode (Sha1).get)
  expect-equals EMPTY-CRC32 (hex.encode (Crc32).get)
  expect-equals EMPTY-CRC16 (hex.encode (Crc16Xmodem).get)
  GOLD-MEMBER := "Hey, everyone! I am from Holland! Isn't that weird?\n"
  sha1.add GOLD-MEMBER
  sha1-io-data.add (FakeData GOLD-MEMBER)
  sha2.add GOLD-MEMBER
  sha2-io-data.add (FakeData GOLD-MEMBER)
  crc32.add GOLD-MEMBER
  crc16.add GOLD-MEMBER
  sha1b := sha1.clone
  sha2b := sha2.clone
  4.repeat: sha1.add GOLD-MEMBER
  4.repeat: sha1-io-data.add (FakeData GOLD-MEMBER)
  4.repeat: sha1b.add GOLD-MEMBER
  4.repeat: sha2.add GOLD-MEMBER
  4.repeat: sha2-io-data.add (FakeData GOLD-MEMBER)
  4.repeat: sha2b.add GOLD-MEMBER
  4.repeat: crc32.add GOLD-MEMBER
  4.repeat: crc16.add GOLD-MEMBER
  sha1-long := sha1.clone
  sha1-long-io-data := sha1-io-data.clone
  sha2-long := sha2.clone
  sha2-long-io-data := sha2-io-data.clone
  expect-equals "7fd2b3793f46a174024e4fb78b17c0dc4c5bf2bc" (hex.encode sha1.get)
  expect-equals "7fd2b3793f46a174024e4fb78b17c0dc4c5bf2bc" (hex.encode sha1-io-data.get)
  expect-equals "7fd2b3793f46a174024e4fb78b17c0dc4c5bf2bc" (hex.encode sha1b.get)
  expect-equals "56185f37" (hex.encode crc32.get)
  expect-equals "5dc2" (hex.encode crc16.get)
  expect-equals "68ffcaadaabb22152c90cfbe4e0cd17ddf2f469d8ea9d021713f1b17c72705b8" (hex.encode sha2.get)
  expect-equals "68ffcaadaabb22152c90cfbe4e0cd17ddf2f469d8ea9d021713f1b17c72705b8" (hex.encode sha2-io-data.get)
  expect-equals "68ffcaadaabb22152c90cfbe4e0cd17ddf2f469d8ea9d021713f1b17c72705b8" (hex.encode sha2b.get)
  expect-already-closed: (sha2.get)   // Can't do this twice.
  expect-already-closed: (sha2b.get)   // Can't do this twice.
  sha1-long.add GOLD-MEMBER * 1000
  sha1-long-io-data.add (FakeData (GOLD-MEMBER * 1000))
  sha2-long.add GOLD-MEMBER * 1000
  sha2-long-io-data.add (FakeData (GOLD-MEMBER * 1000))
  expect-equals sha1-long.get sha1-long-io-data.get
  expect-equals sha2-long.get sha2-long-io-data.get

  sha2 = Sha256
  crc32 = Crc32
  crc16 = Crc16Xmodem

  // Missing trailing '=' signs.
  expect-out-of-range: base64.decode "aaa"
  expect-out-of-range: base64.decode "aa"
  expect-out-of-range: base64.decode "a"

  // Misplaced '=' sign
  expect-out-of-range: base64.decode "=AAA"
  expect-out-of-range: base64.decode "A=AA"
  expect-out-of-range: base64.decode "AA=A"

  // Illegal characters
  expect-out-of-range: base64.decode "aaa_"
  expect-out-of-range: base64.decode "aaa\n"
  expect-out-of-range: base64.decode "aaa."
  expect-out-of-range: base64.decode "aaa@"

  // Unused bits are not zero
  expect-out-of-range: base64.decode "AAa="
  expect-out-of-range: base64.decode "Aa=="
  expect-out-of-range: base64.decode "A4=="

hamming-test:
  // The Hamming test routine can encode any 11 bit number to a 16 bit number.
  // It can correct any bit flip in the 16 bit number and detect any two bit flips.
  (1 << 11).repeat: | input |
    correct := hamming.encode-16-11 input
    // No bit errors.
    expect-equals input (hamming.fix-16-11 correct)
    11.repeat: | bit-flip-1 |
      11.repeat: | bit-flip-2 |
        if bit-flip-1 == bit-flip-2:
          // Just flip one bit.  This should be correctable.
          expect-equals
            input
            hamming.fix-16-11 correct ^ (1 << bit-flip-1)
        else:
          // Flip two bits.  This should be detectable
          expect-equals
            null
            hamming.fix-16-11 correct ^ (1 << bit-flip-1) ^ (1 << bit-flip-2)

aead-simple-test:
  key := ByteArray 16: core.random 256
  initialization-vector := ByteArray 12: core.random 256

  encrypted := (AesGcm.encryptor key initialization-vector).encrypt DREAM

  expect-equals DREAM.size + 16 encrypted.size
  expect-not-equals DREAM[..DREAM.size].to-byte-array DREAM

  round-trip := (AesGcm.decryptor key initialization-vector).decrypt encrypted

  expect-equals DREAM.to-byte-array round-trip

  encrypted-io-data := (AesGcm.encryptor key initialization-vector).encrypt (FakeData DREAM)
  expect-equals encrypted encrypted-io-data

chacha-test:
  // Test vectors from RFC 7539.
  KEY ::= #[
      0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0,
      0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0,
  ]
  IV ::= #[0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
  AAD ::= #[0xf3, 0x33, 0x88, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x91]
  EXPECTED-TAG ::= #[0xee, 0xad, 0x9d, 0x67, 0x89, 0x0c, 0xbb, 0x22, 0x39, 0x23, 0x36, 0xfe, 0xa1, 0x85, 0x1f, 0x38]
  EXPECTED-CIPHERTEXT ::= #[
      0x64, 0xa0, 0x86, 0x15, 0x75, 0x86, 0x1a, 0xf4, 0x60, 0xf0, 0x62, 0xc7, 0x9b, 0xe6, 0x43, 0xbd,
      0x5e, 0x80, 0x5c, 0xfd, 0x34, 0x5c, 0xf3, 0x89, 0xf1, 0x08, 0x67, 0x0a, 0xc7, 0x6c, 0x8c, 0xb2,
      0x4c, 0x6c, 0xfc, 0x18, 0x75, 0x5d, 0x43, 0xee, 0xa0, 0x9e, 0xe9, 0x4e, 0x38, 0x2d, 0x26, 0xb0,
      0xbd, 0xb7, 0xb7, 0x3c, 0x32, 0x1b, 0x01, 0x00, 0xd4, 0xf0, 0x3b, 0x7f, 0x35, 0x58, 0x94, 0xcf,
      0x33, 0x2f, 0x83, 0x0e, 0x71, 0x0b, 0x97, 0xce, 0x98, 0xc8, 0xa8, 0x4a, 0xbd, 0x0b, 0x94, 0x81,
      0x14, 0xad, 0x17, 0x6e, 0x00, 0x8d, 0x33, 0xbd, 0x60, 0xf9, 0x82, 0xb1, 0xff, 0x37, 0xc8, 0x55,
      0x97, 0x97, 0xa0, 0x6e, 0xf4, 0xf0, 0xef, 0x61, 0xc1, 0x86, 0x32, 0x4e, 0x2b, 0x35, 0x06, 0x38,
      0x36, 0x06, 0x90, 0x7b, 0x6a, 0x7c, 0x02, 0xb0, 0xf9, 0xf6, 0x15, 0x7b, 0x53, 0xc8, 0x67, 0xe4,
      0xb9, 0x16, 0x6c, 0x76, 0x7b, 0x80, 0x4d, 0x46, 0xa5, 0x9b, 0x52, 0x16, 0xcd, 0xe7, 0xa4, 0xe9,
      0x90, 0x40, 0xc5, 0xa4, 0x04, 0x33, 0x22, 0x5e, 0xe2, 0x82, 0xa1, 0xb0, 0xa0, 0x6c, 0x52, 0x3e,
      0xaf, 0x45, 0x34, 0xd7, 0xf8, 0x3f, 0xa1, 0x15, 0x5b, 0x00, 0x47, 0x71, 0x8c, 0xbc, 0x54, 0x6a,
      0x0d, 0x07, 0x2b, 0x04, 0xb3, 0x56, 0x4e, 0xea, 0x1b, 0x42, 0x22, 0x73, 0xf5, 0x48, 0x27, 0x1a,
      0x0b, 0xb2, 0x31, 0x60, 0x53, 0xfa, 0x76, 0x99, 0x19, 0x55, 0xeb, 0xd6, 0x31, 0x59, 0x43, 0x4e,
      0xce, 0xbb, 0x4e, 0x46, 0x6d, 0xae, 0x5a, 0x10, 0x73, 0xa6, 0x72, 0x76, 0x27, 0x09, 0x7a, 0x10,
      0x49, 0xe6, 0x17, 0xd9, 0x1d, 0x36, 0x10, 0x94, 0xfa, 0x68, 0xf0, 0xff, 0x77, 0x98, 0x71, 0x30,
      0x30, 0x5b, 0xea, 0xba, 0x2e, 0xda, 0x04, 0xdf, 0x99, 0x7b, 0x71, 0x4d, 0x6c, 0x6f, 0x2c, 0x29,
      0xa6, 0xad, 0x5c, 0xb4, 0x02, 0x2b, 0x02, 0x70, 0x9b,
  ]
  EXPECTED-PLAINTEXT ::= """
      Internet-Drafts are draft documents valid for a maximum of six months \
      and may be updated, replaced, or obsoleted by other documents at any \
      time. It is inappropriate to use Internet-Drafts as reference material \
      or to cite them other than as /“work in progress./”"""

  encrypted := (ChaCha20Poly1305.encryptor KEY IV).encrypt EXPECTED-PLAINTEXT --authenticated-data=AAD
  decrypted := (ChaCha20Poly1305.decryptor KEY IV).decrypt EXPECTED-CIPHERTEXT --authenticated-data=AAD --verification-tag=EXPECTED-TAG
  expect-equals (EXPECTED-CIPHERTEXT + EXPECTED-TAG) encrypted
  expect-equals EXPECTED-PLAINTEXT.to-byte-array decrypted

sip-test:
  key := ByteArray 16: it

  in := ByteArray 64

  64.repeat: | size |
    in[size] = size
    hash-8  := siphash in[0..size] key --output-length=8
    expect-equals SIP-VECTOR-8[size] hash-8

    hash-16 := siphash in[0..size] key --output-length=16
    expect-equals SIP-VECTOR-16[size] hash-16

    hash-16-io-data := siphash (FakeData in[0..size]) key --output-length=16
    expect-equals SIP-VECTOR-16[size] hash-16-io-data

    (size - 1).repeat:
      part1 := in[0..it + 1]
      part2 := in[it + 1..size]

      h8 := Siphash key --output-length=8
      h8.add part1
      h8b := h8.clone
      h8.add part2
      h8b.add part2
      result8 := h8.get
      result8b := h8b.get
      expect-equals SIP-VECTOR-8[size] result8
      expect-equals SIP-VECTOR-8[size] result8b

      h16 := Siphash key --output-length=16
      h16.add part1
      h16b := h16.clone
      h16.add part2
      h16b.add part2
      result16 := h16.get
      result16b := h16b.get
      expect-equals SIP-VECTOR-16[size] result16
      expect-equals SIP-VECTOR-16[size] result16b

blake-test:
  sum := blake2s "abc"
  expect-equals "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982" (hex.encode sum)

  sum2 := blake2s ""
  expect-equals "69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9" (hex.encode sum2)

adler-test:
  VECTORS ::= [
      ["", "00000001"],
      ["a", "00620062"],
      ["abc", "024d0127"],
      ["message digest", "29750586"],
      ["abcdefghijklmnopqrstuvwxyz", "90860b20"],
      ["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "8adb150c"],
      ["12345678901234567890123456789012345678901234567890123456789012345678901234567890", "97b61069"]
  ]

  for i := -1; i < VECTORS.size; i++:
    test := VECTORS[i < 0 ? 0 : i]
    input := test[0]
    if i < 0: input = FakeData input
    output := test[1]
    adler1 := Adler32
    cut := input.byte-size / 2
    adler1.add (input.byte-slice 0 cut)
    adler2 := adler1.clone
    [adler1, adler2].do: | adler |
      adler.add (input.byte-slice cut input.byte-size)
      result := adler.get
      expected := ((List result.size: result[it]).map: "$(%02x it)").join ""
      expect-equals output expected

md5-test:
  check := : | message digest |
    message.size.repeat: | split |
      md5a := Md5
      md5a.add message[0..split]
      md5b := md5a.clone
      md5a.add message[split..]
      md5b.add message[split..]
      expect-bytes-equal digest md5a.get
      expect-bytes-equal digest md5b.get
  STANDARD-MD5-CASES.do check
  GENERATED-MD5-CASES.do check
  check.call
      DREAM
      #[0x9f, 0x14, 0x35, 0x02, 0x7c, 0x35, 0x43, 0xd2, 0x0d, 0x00, 0x5c, 0xb6, 0xe2, 0x6b, 0x26, 0xa6]

hmac-test:
  // Test vectors from RFC 2104.
  hmaccer := Hmac --block-size=Md5.BLOCK-SIZE (ByteArray 16: 0xb):: Md5
  hmaccer.add "Hi There"
  expect-equals #[0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d] hmaccer.get

  hmaccer = Hmac --block-size=Md5.BLOCK-SIZE "Jefe":: Md5
  hmaccer.add "what do ya want for nothing?"
  expect-equals #[0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38] hmaccer.get

  DD-50-ANSWER ::= #[0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6]
  hmaccer = Hmac --block-size=Md5.BLOCK-SIZE (ByteArray 16: 0xaa):: Md5
  hmaccer.add (ByteArray 50: 0xdd)
  expect-equals DD-50-ANSWER hmaccer.get

  // Test clone.
  hmaccer = Hmac --block-size=Md5.BLOCK-SIZE (ByteArray 16: 0xaa):: Md5
  hmaccer.add (ByteArray 25: 0xdd)
  hmaccer2 := hmaccer.clone
  hmaccer.add (ByteArray 25: 0xdd)
  hmaccer2.add (ByteArray 25: 0xdd)
  expect-equals DD-50-ANSWER hmaccer.get
  expect-equals DD-50-ANSWER hmaccer2.get

  // Test vectors from RFC 4231.
  key/any := ByteArray 20: 0x0b
  data/any := "Hi There"

  expect-equals #[0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19, 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f,
                  0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f, 0x53, 0x68, 0x4b, 0x22]
      hmac-sha224 --key=key data
  expect-equals #[0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
                  0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7]
      hmac-sha256 --key=key data
  expect-equals #[0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, 0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f,
                  0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6, 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c,
                  0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f, 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6]
      hmac-sha384 --key=key data
  expect-equals #[0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
                  0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde,
                  0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02, 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4,
                  0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70, 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54]
      hmac-sha512 --key=key data

  key = "Jefe"
  data = "what do ya want for nothing?"

  expect-equals #[0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f,
                  0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00, 0x8f, 0xd0, 0x5e, 0x44]
      hmac-sha224 --key=key data
  expect-equals #[0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
                  0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43]
      hmac-sha256 --key=key data
  expect-equals #[0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b,
                  0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47, 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e,
                  0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7, 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49]
      hmac-sha384 --key=key data
  expect-equals #[0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
                  0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54,
                  0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a, 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd,
                  0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37]
      hmac-sha512 --key=key data

  key = ByteArray 20: 0xaa
  data = ByteArray 50: 0xdd

  expect-equals #[0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, 0xd2, 0x64,
                  0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, 0xec, 0x83, 0x33, 0xea]
      hmac-sha224 --key=key data
  expect-equals #[0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
                  0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe]
      hmac-sha256 --key=key data
  expect-equals #[0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, 0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f,
                  0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb, 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b,
                  0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9, 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27]
      hmac-sha384 --key=key data
  expect-equals #[0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9,
                  0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39,
                  0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8, 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07,
                  0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb]
      hmac-sha512 --key=key data

  key = ByteArray 25: it + 1
  data = ByteArray 50: 0xcd

  expect-equals #[0x6c, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3c, 0xac, 0x6a, 0x2a, 0xbc, 0x1b, 0xb3, 0x82, 0x62, 0x7c,
                  0xec, 0x6a, 0x90, 0xd8, 0x6e, 0xfc, 0x01, 0x2d, 0xe7, 0xaf, 0xec, 0x5a]
      hmac-sha224 --key=key data
  expect-equals #[0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
                  0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b]
      hmac-sha256 --key=key data
  expect-equals #[0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85, 0x19, 0x33, 0xab, 0x62, 0x90, 0xaf, 0x6c, 0xa7,
                  0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c, 0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e,
                  0x68, 0x01, 0xdd, 0x23, 0xc4, 0xa7, 0xd6, 0x79, 0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb]
      hmac-sha384 --key=key data
  expect-equals #[0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7,
                  0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb,
                  0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4, 0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63,
                  0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d, 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd]
      hmac-sha512 --key=key data

  key = ByteArray 20: 0x0c
  data = "Test With Truncation"

  expect-equals #[0x0e, 0x2a, 0xea, 0x68, 0xa9, 0x0c, 0x8d, 0x37, 0xc9, 0x88, 0xbc, 0xdb, 0x9f, 0xca, 0x6f, 0xa8]
      (hmac-sha224 --key=key data)[..16]
  expect-equals #[0xa3, 0xb6, 0x16, 0x74, 0x73, 0x10, 0x0e, 0xe0, 0x6e, 0x0c, 0x79, 0x6c, 0x29, 0x55, 0x55, 0x2b]
      (hmac-sha256 --key=key data)[..16]
  expect-equals #[0x3a, 0xbf, 0x34, 0xc3, 0x50, 0x3b, 0x2a, 0x23, 0xa4, 0x6e, 0xfc, 0x61, 0x9b, 0xae, 0xf8, 0x97]
      (hmac-sha384 --key=key data)[..16]
  expect-equals #[0x41, 0x5f, 0xad, 0x62, 0x71, 0x58, 0x0a, 0x53, 0x1d, 0x41, 0x79, 0xbc, 0x89, 0x1d, 0x87, 0xa6]
      (hmac-sha512 --key=key data)[..16]

  key = ByteArray 131: 0xaa
  data = "Test Using Larger Than Block-Size Key - Hash Key First"

  expect-equals #[0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad, 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2,
                  0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27, 0x3f, 0xa6, 0x87, 0x0e]
      hmac-sha224 --key=key data
  expect-equals #[0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
                  0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54]
      hmac-sha256 --key=key data
  expect-equals #[0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90, 0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4,
                  0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f, 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6,
                  0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82, 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52]
      hmac-sha384 --key=key data
  expect-equals #[0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb, 0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4,
                  0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1, 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52,
                  0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98, 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52,
                  0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec, 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98]
      hmac-sha512 --key=key data

  key = ByteArray 131: 0xaa
  data = "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."

  expect-equals #[0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02, 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd,
                  0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9, 0xf6, 0xf5, 0x65, 0xd1]
      hmac-sha224 --key=key data
  expect-equals #[0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
                  0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2]
      hmac-sha256 --key=key data
  expect-equals #[0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d, 0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c,
                  0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a, 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5,
                  0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d, 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e]
      hmac-sha384 --key=key data
  expect-equals #[0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba, 0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd,
                  0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86, 0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44,
                  0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1, 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15,
                  0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60, 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58]
      hmac-sha512 --key=key data

random-test:
  tls-get-random_ #[]

  eight-a := ByteArray 8
  eight-b := ByteArray 8

  tls-get-random_ eight-a
  tls-get-random_ eight-b
  // Unlikely in the extreme to get the same random 8 bytes twice.
  expect-not-equals eight-a eight-b
  // Unlikely in the extreme to get eight zero bytes.
  expect-not-equals (ByteArray 8) eight-a
  expect-not-equals (ByteArray 8) eight-b

  // Ensure we don't round down the size written - sooner or later we
  // must get a non-zero value there.
  fifteen := ByteArray 15
  while fifteen[14] == 0:
    tls-get-random_ fifteen

  b32 := ByteArray 32
  10.repeat:
    tls-get-random_ b32
    zeros := 0
    b32.do: if it == 0: zeros++
    expect-equals true (zeros < 8)

SIP-VECTOR-8 ::= [
    #[0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72,],
    #[0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74,],
    #[0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d,],
    #[0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85,],
    #[0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf,],
    #[0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18,],
    #[0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb,],
    #[0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab,],
    #[0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93,],
    #[0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e,],
    #[0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a,],
    #[0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4,],
    #[0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75,],
    #[0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14,],
    #[0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7,],
    #[0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1,],
    #[0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f,],
    #[0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69,],
    #[0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b,],
    #[0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb,],
    #[0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe,],
    #[0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0,],
    #[0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93,],
    #[0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8,],
    #[0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8,],
    #[0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc,],
    #[0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17,],
    #[0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f,],
    #[0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde,],
    #[0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6,],
    #[0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad,],
    #[0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32,],
    #[0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71,],
    #[0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7,],
    #[0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12,],
    #[0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15,],
    #[0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31,],
    #[0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02,],
    #[0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca,],
    #[0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a,],
    #[0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e,],
    #[0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad,],
    #[0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18,],
    #[0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4,],
    #[0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9,],
    #[0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9,],
    #[0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb,],
    #[0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0,],
    #[0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6,],
    #[0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7,],
    #[0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee,],
    #[0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1,],
    #[0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a,],
    #[0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81,],
    #[0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f,],
    #[0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24,],
    #[0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7,],
    #[0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea,],
    #[0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60,],
    #[0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66,],
    #[0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c,],
    #[0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f,],
    #[0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5,],
    #[0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95,],
]

SIP-VECTOR-16 ::= [
    #[0xa3, 0x81, 0x7f, 0x04, 0xba, 0x25, 0xa8, 0xe6, 0x6d, 0xf6, 0x72, 0x14, 0xc7, 0x55, 0x02, 0x93,],
    #[0xda, 0x87, 0xc1, 0xd8, 0x6b, 0x99, 0xaf, 0x44, 0x34, 0x76, 0x59, 0x11, 0x9b, 0x22, 0xfc, 0x45,],
    #[0x81, 0x77, 0x22, 0x8d, 0xa4, 0xa4, 0x5d, 0xc7, 0xfc, 0xa3, 0x8b, 0xde, 0xf6, 0x0a, 0xff, 0xe4,],
    #[0x9c, 0x70, 0xb6, 0x0c, 0x52, 0x67, 0xa9, 0x4e, 0x5f, 0x33, 0xb6, 0xb0, 0x29, 0x85, 0xed, 0x51,],
    #[0xf8, 0x81, 0x64, 0xc1, 0x2d, 0x9c, 0x8f, 0xaf, 0x7d, 0x0f, 0x6e, 0x7c, 0x7b, 0xcd, 0x55, 0x79,],
    #[0x13, 0x68, 0x87, 0x59, 0x80, 0x77, 0x6f, 0x88, 0x54, 0x52, 0x7a, 0x07, 0x69, 0x0e, 0x96, 0x27,],
    #[0x14, 0xee, 0xca, 0x33, 0x8b, 0x20, 0x86, 0x13, 0x48, 0x5e, 0xa0, 0x30, 0x8f, 0xd7, 0xa1, 0x5e,],
    #[0xa1, 0xf1, 0xeb, 0xbe, 0xd8, 0xdb, 0xc1, 0x53, 0xc0, 0xb8, 0x4a, 0xa6, 0x1f, 0xf0, 0x82, 0x39,],
    #[0x3b, 0x62, 0xa9, 0xba, 0x62, 0x58, 0xf5, 0x61, 0x0f, 0x83, 0xe2, 0x64, 0xf3, 0x14, 0x97, 0xb4,],
    #[0x26, 0x44, 0x99, 0x06, 0x0a, 0xd9, 0xba, 0xab, 0xc4, 0x7f, 0x8b, 0x02, 0xbb, 0x6d, 0x71, 0xed,],
    #[0x00, 0x11, 0x0d, 0xc3, 0x78, 0x14, 0x69, 0x56, 0xc9, 0x54, 0x47, 0xd3, 0xf3, 0xd0, 0xfb, 0xba,],
    #[0x01, 0x51, 0xc5, 0x68, 0x38, 0x6b, 0x66, 0x77, 0xa2, 0xb4, 0xdc, 0x6f, 0x81, 0xe5, 0xdc, 0x18,],
    #[0xd6, 0x26, 0xb2, 0x66, 0x90, 0x5e, 0xf3, 0x58, 0x82, 0x63, 0x4d, 0xf6, 0x85, 0x32, 0xc1, 0x25,],
    #[0x98, 0x69, 0xe2, 0x47, 0xe9, 0xc0, 0x8b, 0x10, 0xd0, 0x29, 0x93, 0x4f, 0xc4, 0xb9, 0x52, 0xf7,],
    #[0x31, 0xfc, 0xef, 0xac, 0x66, 0xd7, 0xde, 0x9c, 0x7e, 0xc7, 0x48, 0x5f, 0xe4, 0x49, 0x49, 0x02,],
    #[0x54, 0x93, 0xe9, 0x99, 0x33, 0xb0, 0xa8, 0x11, 0x7e, 0x08, 0xec, 0x0f, 0x97, 0xcf, 0xc3, 0xd9,],
    #[0x6e, 0xe2, 0xa4, 0xca, 0x67, 0xb0, 0x54, 0xbb, 0xfd, 0x33, 0x15, 0xbf, 0x85, 0x23, 0x05, 0x77,],
    #[0x47, 0x3d, 0x06, 0xe8, 0x73, 0x8d, 0xb8, 0x98, 0x54, 0xc0, 0x66, 0xc4, 0x7a, 0xe4, 0x77, 0x40,],
    #[0xa4, 0x26, 0xe5, 0xe4, 0x23, 0xbf, 0x48, 0x85, 0x29, 0x4d, 0xa4, 0x81, 0xfe, 0xae, 0xf7, 0x23,],
    #[0x78, 0x01, 0x77, 0x31, 0xcf, 0x65, 0xfa, 0xb0, 0x74, 0xd5, 0x20, 0x89, 0x52, 0x51, 0x2e, 0xb1,],
    #[0x9e, 0x25, 0xfc, 0x83, 0x3f, 0x22, 0x90, 0x73, 0x3e, 0x93, 0x44, 0xa5, 0xe8, 0x38, 0x39, 0xeb,],
    #[0x56, 0x8e, 0x49, 0x5a, 0xbe, 0x52, 0x5a, 0x21, 0x8a, 0x22, 0x14, 0xcd, 0x3e, 0x07, 0x1d, 0x12,],
    #[0x4a, 0x29, 0xb5, 0x45, 0x52, 0xd1, 0x6b, 0x9a, 0x46, 0x9c, 0x10, 0x52, 0x8e, 0xff, 0x0a, 0xae,],
    #[0xc9, 0xd1, 0x84, 0xdd, 0xd5, 0xa9, 0xf5, 0xe0, 0xcf, 0x8c, 0xe2, 0x9a, 0x9a, 0xbf, 0x69, 0x1c,],
    #[0x2d, 0xb4, 0x79, 0xae, 0x78, 0xbd, 0x50, 0xd8, 0x88, 0x2a, 0x8a, 0x17, 0x8a, 0x61, 0x32, 0xad,],
    #[0x8e, 0xce, 0x5f, 0x04, 0x2d, 0x5e, 0x44, 0x7b, 0x50, 0x51, 0xb9, 0xea, 0xcb, 0x8d, 0x8f, 0x6f,],
    #[0x9c, 0x0b, 0x53, 0xb4, 0xb3, 0xc3, 0x07, 0xe8, 0x7e, 0xae, 0xe0, 0x86, 0x78, 0x14, 0x1f, 0x66,],
    #[0xab, 0xf2, 0x48, 0xaf, 0x69, 0xa6, 0xea, 0xe4, 0xbf, 0xd3, 0xeb, 0x2f, 0x12, 0x9e, 0xeb, 0x94,],
    #[0x06, 0x64, 0xda, 0x16, 0x68, 0x57, 0x4b, 0x88, 0xb9, 0x35, 0xf3, 0x02, 0x73, 0x58, 0xae, 0xf4,],
    #[0xaa, 0x4b, 0x9d, 0xc4, 0xbf, 0x33, 0x7d, 0xe9, 0x0c, 0xd4, 0xfd, 0x3c, 0x46, 0x7c, 0x6a, 0xb7,],
    #[0xea, 0x5c, 0x7f, 0x47, 0x1f, 0xaf, 0x6b, 0xde, 0x2b, 0x1a, 0xd7, 0xd4, 0x68, 0x6d, 0x22, 0x87,],
    #[0x29, 0x39, 0xb0, 0x18, 0x32, 0x23, 0xfa, 0xfc, 0x17, 0x23, 0xde, 0x4f, 0x52, 0xc4, 0x3d, 0x35,],
    #[0x7c, 0x39, 0x56, 0xca, 0x5e, 0xea, 0xfc, 0x3e, 0x36, 0x3e, 0x9d, 0x55, 0x65, 0x46, 0xeb, 0x68,],
    #[0x77, 0xc6, 0x07, 0x71, 0x46, 0xf0, 0x1c, 0x32, 0xb6, 0xb6, 0x9d, 0x5f, 0x4e, 0xa9, 0xff, 0xcf,],
    #[0x37, 0xa6, 0x98, 0x6c, 0xb8, 0x84, 0x7e, 0xdf, 0x09, 0x25, 0xf0, 0xf1, 0x30, 0x9b, 0x54, 0xde,],
    #[0xa7, 0x05, 0xf0, 0xe6, 0x9d, 0xa9, 0xa8, 0xf9, 0x07, 0x24, 0x1a, 0x2e, 0x92, 0x3c, 0x8c, 0xc8,],
    #[0x3d, 0xc4, 0x7d, 0x1f, 0x29, 0xc4, 0x48, 0x46, 0x1e, 0x9e, 0x76, 0xed, 0x90, 0x4f, 0x67, 0x11,],
    #[0x0d, 0x62, 0xbf, 0x01, 0xe6, 0xfc, 0x0e, 0x1a, 0x0d, 0x3c, 0x47, 0x51, 0xc5, 0xd3, 0x69, 0x2b,],
    #[0x8c, 0x03, 0x46, 0x8b, 0xca, 0x7c, 0x66, 0x9e, 0xe4, 0xfd, 0x5e, 0x08, 0x4b, 0xbe, 0xe7, 0xb5,],
    #[0x52, 0x8a, 0x5b, 0xb9, 0x3b, 0xaf, 0x2c, 0x9c, 0x44, 0x73, 0xcc, 0xe5, 0xd0, 0xd2, 0x2b, 0xd9,],
    #[0xdf, 0x6a, 0x30, 0x1e, 0x95, 0xc9, 0x5d, 0xad, 0x97, 0xae, 0x0c, 0xc8, 0xc6, 0x91, 0x3b, 0xd8,],
    #[0x80, 0x11, 0x89, 0x90, 0x2c, 0x85, 0x7f, 0x39, 0xe7, 0x35, 0x91, 0x28, 0x5e, 0x70, 0xb6, 0xdb,],
    #[0xe6, 0x17, 0x34, 0x6a, 0xc9, 0xc2, 0x31, 0xbb, 0x36, 0x50, 0xae, 0x34, 0xcc, 0xca, 0x0c, 0x5b,],
    #[0x27, 0xd9, 0x34, 0x37, 0xef, 0xb7, 0x21, 0xaa, 0x40, 0x18, 0x21, 0xdc, 0xec, 0x5a, 0xdf, 0x89,],
    #[0x89, 0x23, 0x7d, 0x9d, 0xed, 0x9c, 0x5e, 0x78, 0xd8, 0xb1, 0xc9, 0xb1, 0x66, 0xcc, 0x73, 0x42,],
    #[0x4a, 0x6d, 0x80, 0x91, 0xbf, 0x5e, 0x7d, 0x65, 0x11, 0x89, 0xfa, 0x94, 0xa2, 0x50, 0xb1, 0x4c,],
    #[0x0e, 0x33, 0xf9, 0x60, 0x55, 0xe7, 0xae, 0x89, 0x3f, 0xfc, 0x0e, 0x3d, 0xcf, 0x49, 0x29, 0x02,],
    #[0xe6, 0x1c, 0x43, 0x2b, 0x72, 0x0b, 0x19, 0xd1, 0x8e, 0xc8, 0xd8, 0x4b, 0xdc, 0x63, 0x15, 0x1b,],
    #[0xf7, 0xe5, 0xae, 0xf5, 0x49, 0xf7, 0x82, 0xcf, 0x37, 0x90, 0x55, 0xa6, 0x08, 0x26, 0x9b, 0x16,],
    #[0x43, 0x8d, 0x03, 0x0f, 0xd0, 0xb7, 0xa5, 0x4f, 0xa8, 0x37, 0xf2, 0xad, 0x20, 0x1a, 0x64, 0x03,],
    #[0xa5, 0x90, 0xd3, 0xee, 0x4f, 0xbf, 0x04, 0xe3, 0x24, 0x7e, 0x0d, 0x27, 0xf2, 0x86, 0x42, 0x3f,],
    #[0x5f, 0xe2, 0xc1, 0xa1, 0x72, 0xfe, 0x93, 0xc4, 0xb1, 0x5c, 0xd3, 0x7c, 0xae, 0xf9, 0xf5, 0x38,],
    #[0x2c, 0x97, 0x32, 0x5c, 0xbd, 0x06, 0xb3, 0x6e, 0xb2, 0x13, 0x3d, 0xd0, 0x8b, 0x3a, 0x01, 0x7c,],
    #[0x92, 0xc8, 0x14, 0x22, 0x7a, 0x6b, 0xca, 0x94, 0x9f, 0xf0, 0x65, 0x9f, 0x00, 0x2a, 0xd3, 0x9e,],
    #[0xdc, 0xe8, 0x50, 0x11, 0x0b, 0xd8, 0x32, 0x8c, 0xfb, 0xd5, 0x08, 0x41, 0xd6, 0x91, 0x1d, 0x87,],
    #[0x67, 0xf1, 0x49, 0x84, 0xc7, 0xda, 0x79, 0x12, 0x48, 0xe3, 0x2b, 0xb5, 0x92, 0x25, 0x83, 0xda,],
    #[0x19, 0x38, 0xf2, 0xcf, 0x72, 0xd5, 0x4e, 0xe9, 0x7e, 0x94, 0x16, 0x6f, 0xa9, 0x1d, 0x2a, 0x36,],
    #[0x74, 0x48, 0x1e, 0x96, 0x46, 0xed, 0x49, 0xfe, 0x0f, 0x62, 0x24, 0x30, 0x16, 0x04, 0x69, 0x8e,],
    #[0x57, 0xfc, 0xa5, 0xde, 0x98, 0xa9, 0xd6, 0xd8, 0x00, 0x64, 0x38, 0xd0, 0x58, 0x3d, 0x8a, 0x1d,],
    #[0x9f, 0xec, 0xde, 0x1c, 0xef, 0xdc, 0x1c, 0xbe, 0xd4, 0x76, 0x36, 0x74, 0xd9, 0x57, 0x53, 0x59,],
    #[0xe3, 0x04, 0x0c, 0x00, 0xeb, 0x28, 0xf1, 0x53, 0x66, 0xca, 0x73, 0xcb, 0xd8, 0x72, 0xe7, 0x40,],
    #[0x76, 0x97, 0x00, 0x9a, 0x6a, 0x83, 0x1d, 0xfe, 0xcc, 0xa9, 0x1c, 0x59, 0x93, 0x67, 0x0f, 0x7a,],
    #[0x58, 0x53, 0x54, 0x23, 0x21, 0xf5, 0x67, 0xa0, 0x05, 0xd5, 0x47, 0xa4, 0xf0, 0x47, 0x59, 0xbd,],
    #[0x51, 0x50, 0xd1, 0x77, 0x2f, 0x50, 0x83, 0x4a, 0x50, 0x3e, 0x06, 0x9a, 0x97, 0x3f, 0xbd, 0x7c,],
]

DREAM ::= """
    Sarnac had worked almost continuously for the better part of a year
    upon some very subtle chemical reactions of the nervous cells of the
    sympathetic system.  His first enquiries had led to the opening out
    of fresh and surprising possibilities, and these again had lured him
    on to still broader and more fascinating prospects.  He worked
    perhaps too closely; he found his hope and curiosity unimpaired, but
    there was less delicacy of touch in his manipulation, and he was
    thinking less quickly and accurately.  He needed a holiday.  He had
    come to the end of a chapter in his work and wished to brace himself
    for a new beginning.  Sunray had long hoped to be away with him; she,
    too, was at a phase in her work when interruption was possible, and
    so the two went off together to wander among the lakes and mountains.

    Their companionship was at a very delightful stage.  Their close
    relationship and their friendship was of old standing, so that they
    were quite at their ease with one another, yet they were not too
    familiar to have lost the keen edge of their interest in each other's
    proceedings.  Sunray was very much in love with Sarnac and glad, and
    Sarnac was always happy and pleasantly exalted when Sunray was near
    him.  Sunray was the richer-hearted and cleverer lover.  They talked
    of everything in the world but Sarnac's work because that had to rest
    and grow fresh again.  Of her own work Sunray talked abundantly.  She
    had been making stories and pictures of happiness and sorrow in the
    past ages of the world, and she was full of curious speculations
    about the ways in which the ancestral mind has thought and felt.

    They played with boats upon the great lake for some days, they sailed
    and paddled and drew up their canoe among the sweet-scented rushes of
    the islands and bathed and swam.  They went from one guest-house to
    another upon the water and met many interesting and refreshing
    people.  In one house an old man of ninety-eight was staying: he was
    amusing his declining years by making statuettes of the greatest
    beauty and humour; it was wonderful to see the clay take shape in his
    hands.  Moreover, he had a method of cooking the lake fish that was
    very appetising, and he made a great dish of them so that everyone
    who was dining in the place could have some.  And there was a
    musician who made Sunray talk about the days gone by, and afterwards
    he played music with his own hands on a clavier to express the
    ancient feelings of men.  He played one piece that was, he explained,
    two thousand years old; it was by a man named Chopin, and it was
    called the Revolutionary Etude.  Sunray could not have believed a
    piano capable of such passionate resentment.  After that he played
    grotesque and angry battle music and crude marching tunes from those
    half-forgotten times, and then he invented wrathful and passionate
    music of his own.
    """

STANDARD-MD5-CASES ::= {
  "":
  #[0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e],
  "a":
  #[0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61],
  "abc":
  #[0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72],
  "message digest":
  #[0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0],
  "abcdefghijklmnopqrstuvwxyz":
  #[0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b],
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789":
  #[0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f],
  "12345678901234567890123456789012345678901234567890123456789012345678901234567890":
  #[0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a],
}

GENERATED-MD5-CASES ::= {
  #[0x30, 0x72, 0xc0, 0xd0, 0xef, 0xfa, 0x23, 0xa7, 0xdc, 0x9d, 0x38, 0x7b, 0x60, 0x2f, 0x8b, 0x13,
    0xa4, 0xd4, 0x32, 0x5f, 0x88, 0xa8, 0xbb, 0x07, 0x7a, 0x69, 0xab, 0xde, 0x19, 0xcb, 0xf6, 0x11]:
  #[0xa8, 0x1f, 0x9d, 0x87, 0xd6, 0x09, 0x1f, 0x52, 0xd4, 0x87, 0xb3, 0xfe, 0x17, 0x06, 0x52, 0xe7],
  #[0x63, 0x3a, 0x51, 0x23, 0xea, 0xed, 0x88, 0xf9, 0xf1, 0xde, 0x4a, 0x01, 0xaa, 0x8e, 0x68, 0xa2,
    0xff, 0xc1, 0xa9, 0xbb, 0x4b, 0x41, 0x9d, 0xf3, 0x7e, 0x66, 0x25, 0xbd, 0x45, 0xe5, 0x43, 0xb6,
    0x9a, 0x5a, 0xaf, 0xfd, 0xbb, 0x0e, 0xab, 0x3f, 0xd6, 0x2f, 0x7b, 0x8f, 0x0c, 0xb0, 0x0c, 0x50,
    0x70, 0xb8, 0x86, 0xec, 0x47, 0x99, 0x8c, 0x15, 0x6b, 0x9f, 0x64, 0x72, 0x04, 0x61, 0x1b]:
  #[0x84, 0x4c, 0xd7, 0x6a, 0x7c, 0x39, 0xf5, 0xfb, 0xff, 0xb3, 0x62, 0x65, 0x2c, 0xf1, 0xd2, 0x4e],
  #[0xd6, 0x91, 0x67, 0x49, 0x75, 0xf0, 0xdc, 0x0f, 0xc4, 0x7c, 0xa0, 0xc0, 0xdd, 0xee, 0x24, 0x05,
    0xbc, 0xe1, 0xf3, 0x36, 0x1d, 0xe5, 0x7b, 0xa7, 0xa4, 0xc5, 0x84, 0x26, 0x37, 0x40, 0xf8, 0x83,
    0x60, 0xba, 0x2c, 0x96, 0x33, 0x31, 0x01, 0x7d, 0xdb, 0x30, 0x4a, 0xe2, 0x02, 0xfb, 0xf1, 0xae,
    0xf5, 0xf7, 0xa4, 0x19, 0x7e, 0x7e, 0xfc, 0xff, 0xc9, 0x26, 0x99, 0x96, 0xdd, 0xd8, 0xdf, 0x43]:
  #[0xd6, 0x65, 0x65, 0x0e, 0x92, 0xf4, 0x10, 0x20, 0x31, 0x97, 0x91, 0x91, 0xac, 0x37, 0x21, 0xb3],
  #[0x01, 0x64, 0x04, 0x1e, 0x2b, 0xfe, 0xe3, 0xaa, 0x94, 0x10, 0x6d, 0x14, 0xec, 0x68, 0xeb, 0x36,
    0x8f, 0x1d, 0xa1, 0xef, 0xf2, 0xcb, 0xd1, 0x51, 0xb6, 0x12, 0xdb, 0x15, 0x0f, 0x42, 0xe0, 0x0e,
    0xb0, 0xe5, 0x18, 0x78, 0x6d, 0x35, 0xdf, 0x61, 0x95, 0x4f, 0x40, 0x2c, 0xf2, 0x78, 0x30, 0x53,
    0xb4, 0x75, 0x81, 0xe7, 0xe2, 0xe9, 0xe2, 0xfc, 0xc3, 0xf4, 0xf5, 0xd3, 0xeb, 0x2f, 0xf6, 0x5e,
    0x11]:
  #[0x16, 0xc5, 0x90, 0xe1, 0x78, 0x20, 0x30, 0x91, 0xc5, 0xcc, 0x67, 0xd1, 0xca, 0x00, 0xd6, 0x44],
  #[0x60, 0x34, 0x2d, 0x85, 0x98, 0x90, 0x3a, 0xc1, 0x7b, 0x24, 0x98, 0xf3, 0xd0, 0x48, 0x36, 0xdf,
    0xa7, 0x12, 0xee, 0xc5, 0x44, 0x30, 0x3a, 0x5f, 0x73, 0x3e, 0x13, 0x44, 0xef, 0x93, 0x08, 0x5d,
    0xbc, 0xbe, 0x32, 0xb1, 0x8c, 0x9a, 0x4f, 0xe9, 0x32, 0x3d, 0xea, 0x88, 0x40, 0xed, 0x08, 0xa4,
    0x20, 0x28, 0x3c, 0x3a, 0x15, 0x8b, 0x57, 0xd5, 0x9f, 0x02, 0x65, 0xa2, 0xd3, 0xcf, 0xa9, 0x9a,
    0xad, 0xa6, 0xfc, 0x97, 0x36, 0x63, 0xf0, 0x24, 0x7b, 0x23, 0x3a, 0x62, 0x3d, 0x1d, 0xc5, 0x26,
    0xbc, 0x1c, 0xe8, 0x59, 0xac, 0x47, 0x41, 0xec, 0xae, 0xba, 0x31, 0x77, 0x3a, 0x27, 0x9c, 0x4e,
    0x3e, 0x4d, 0x0f, 0xae, 0x13, 0x59, 0x90, 0x33, 0x67, 0x6e, 0xd6, 0xc1, 0x5d, 0xa5, 0xeb, 0x9e,
    0xa1, 0x4e, 0x09, 0xd8, 0x93, 0x12, 0x03, 0xa6, 0x66, 0x01, 0xcc, 0x8f, 0xe0, 0x32, 0x78]:
  #[0xed, 0xa2, 0x83, 0x00, 0x04, 0xc8, 0x9c, 0xae, 0x6b, 0x22, 0xe6, 0x3b, 0x3a, 0xa4, 0x01, 0x9b],
  #[0x8d, 0x15, 0xa6, 0x32, 0xa2, 0x43, 0x7d, 0xe5, 0xc9, 0x31, 0x97, 0x45, 0xcf, 0xe7, 0x77, 0x61,
    0x1d, 0x6e, 0x18, 0x8f, 0x0e, 0x20, 0xe7, 0x94, 0xf9, 0x98, 0x78, 0x2d, 0xb6, 0x8d, 0x1a, 0x65,
    0x30, 0xe1, 0x61, 0x24, 0x48, 0x43, 0x88, 0x76, 0x73, 0x0b, 0x1c, 0x55, 0x95, 0x29, 0x42, 0x10,
    0xde, 0x99, 0x1b, 0xc6, 0xad, 0x90, 0xc5, 0xeb, 0x29, 0x87, 0x6c, 0xb5, 0x53, 0x57, 0x2a, 0xd6,
    0xf8, 0x57, 0x1f, 0x12, 0x93, 0xa6, 0x1a, 0x90, 0xa6, 0xd2, 0x23, 0x76, 0x2d, 0x55, 0x39, 0xc2,
    0x08, 0xd3, 0x6e, 0x67, 0x62, 0x1b, 0xa4, 0x80, 0x99, 0x7e, 0xa7, 0x2d, 0xd2, 0x4f, 0xe3, 0xd4,
    0x39, 0xf9, 0x0a, 0xd5, 0x3d, 0x70, 0xc1, 0xf5, 0x17, 0xf3, 0x86, 0x39, 0x7b, 0x49, 0x43, 0xeb,
    0xe8, 0x48, 0xbe, 0x25, 0xd2, 0x84, 0xae, 0x8c, 0x46, 0x39, 0x8b, 0xd2, 0x73, 0x92, 0x3c, 0x5a]:
  #[0x16, 0x82, 0x67, 0xea, 0x97, 0x00, 0x3a, 0xce, 0xfd, 0x78, 0x0f, 0xbe, 0xd1, 0x07, 0x9d, 0x6f],
  #[0xf2, 0x3c, 0xff, 0xb8, 0x78, 0xee, 0x1a, 0x0a, 0x0a, 0x97, 0x71, 0x2b, 0x24, 0xc1, 0x5a, 0x78,
    0x88, 0xb1, 0x72, 0xb2, 0x4e, 0x70, 0x2f, 0x86, 0xd6, 0xd0, 0x93, 0xb4, 0x0c, 0x78, 0xc5, 0xff,
    0xcb, 0xfa, 0x35, 0x84, 0x98, 0xbf, 0x3e, 0x11, 0xf4, 0xfc, 0xfa, 0x9f, 0x1a, 0x05, 0x98, 0xac,
    0xf5, 0x49, 0xc1, 0x58, 0xc7, 0xe6, 0x21, 0x2a, 0x9a, 0xb8, 0xc7, 0xca, 0x41, 0x7e, 0xe2, 0x43,
    0xb6, 0xc8, 0xa2, 0x69, 0x5d, 0xfb, 0x66, 0xc0, 0xb2, 0xf4, 0xbd, 0x2e, 0x48, 0x4d, 0x3a, 0x5f,
    0x21, 0x68, 0xc9, 0xe9, 0x77, 0xd9, 0x6f, 0x2c, 0xd0, 0xe2, 0xc2, 0x3a, 0x09, 0x29, 0xce, 0x3c,
    0xe5, 0x66, 0xa8, 0xaf, 0x42, 0x9e, 0x5b, 0x27, 0x95, 0x3e, 0x9b, 0x6e, 0x50, 0x8b, 0xde, 0x37,
    0x52, 0x53, 0x41, 0x7a, 0x9a, 0x65, 0xce, 0x47, 0x41, 0xb9, 0xbe, 0x9b, 0x6d, 0xdc, 0xb0, 0x12,
    0x16]:
  #[0xe3, 0x0e, 0x82, 0xf4, 0x02, 0x8f, 0x02, 0x21, 0x17, 0x85, 0xc2, 0x07, 0xfc, 0x35, 0xcd, 0xac],
  #[0x70, 0xa9, 0x4d, 0xc6, 0xd4, 0x3f, 0xf3, 0x27, 0xbd, 0x09, 0xec, 0xf6, 0xec, 0x95, 0xa8, 0xd2,
    0xae, 0x4f, 0xde, 0x7d, 0xa2, 0x1e, 0xb7, 0xc4, 0x2b, 0x16, 0xd4, 0x24, 0xc4, 0x98, 0x7e, 0x3a,
    0xe9, 0x4c, 0xd4, 0x72, 0xda, 0xf1, 0x47, 0x4a, 0xdb, 0xf9, 0x1f, 0xc9, 0x9c, 0x3d, 0xee, 0x78,
    0xc3, 0x1a, 0xfb, 0x57, 0x59, 0xe6, 0x33, 0x7c, 0x0a, 0x36, 0x68, 0x37, 0xd3, 0xb7, 0xcc, 0x10,
    0x31, 0x61, 0x86, 0x1d, 0x14, 0xa8, 0xda, 0x98, 0xbc, 0xdf, 0x96, 0x69, 0xa7, 0x93, 0xe4, 0xe3,
    0x6a, 0x78, 0xf5, 0x8c, 0xe3, 0x4e, 0x82, 0x5b, 0x66, 0x98, 0xb5, 0x4f, 0xd7, 0xec, 0x6c, 0x2a,
    0x12, 0x8c, 0x87, 0x10, 0x83, 0x21, 0x26, 0xa8, 0xc0, 0xb0, 0xb2, 0xbc, 0x24, 0x67, 0x15, 0xea,
    0x88, 0xfe, 0xf8, 0xd2, 0x30, 0x62, 0x97, 0x7c, 0xd4, 0x37, 0xe1, 0x13, 0x2d, 0x2b, 0xa6, 0xe3,
    0x24, 0xbf, 0x46, 0xb9, 0xe4, 0xf4, 0x1c, 0xb3, 0xb8, 0x96, 0xe6, 0x0a, 0x46, 0xab, 0xfb, 0xb4,
    0xab, 0x6b, 0x24, 0x1c, 0x7a, 0x5a, 0x46, 0x70, 0xc3, 0xa5, 0xe7, 0xed, 0x5a, 0xdf, 0xaa, 0x0c,
    0xe9, 0xa9, 0x8e, 0x8a, 0xdd, 0x25, 0x61, 0xae, 0x77, 0xf0, 0xbb, 0xe4, 0x3a, 0x62, 0x55, 0x92,
    0xdd, 0xfb, 0xe1, 0x50, 0x5d, 0xde, 0x9a, 0xd6, 0x4b, 0xfa, 0xfa, 0x3a, 0xc3, 0xea, 0x8d, 0x0e,
    0x57, 0xb6, 0xd5, 0x21, 0x41, 0x52, 0x33, 0x13, 0x15, 0xb7, 0xb2, 0x73, 0x56, 0xf6, 0x9c, 0xa8,
    0x0f, 0x70, 0x5a, 0x8b, 0x24, 0xc7, 0x2c, 0xd9, 0x52, 0xdf, 0x14, 0x86, 0x82, 0x37, 0x04, 0x2b,
    0x0f, 0xa5, 0x31, 0x85, 0xcc, 0x93, 0x41, 0x6c, 0x3e, 0x84, 0x3b, 0x06, 0x30, 0xba, 0xa1, 0xba,
    0x4a, 0x37, 0xe4, 0x7a, 0x0d, 0x0c, 0x48, 0xa9, 0x76, 0x70, 0xf8, 0x39, 0x23, 0x3c, 0x3b, 0x21,
    0x11, 0xb9, 0x3f, 0x7d, 0xad, 0x8a, 0x97, 0xeb, 0x3e, 0x74, 0xec, 0x10, 0xa0, 0x71, 0x58, 0x08,
    0xfa, 0x7e, 0x47, 0x4f, 0x67, 0x06, 0x69, 0x04, 0xe0, 0x39, 0xc8, 0x8f, 0x75, 0x2a, 0x56, 0x63,
    0x99, 0x8b, 0x53, 0x64, 0xc8, 0x1c, 0xb6, 0x30, 0x02, 0xdb, 0xcb, 0xbd, 0x39, 0x1a, 0xb3, 0xb7,
    0xf1, 0x87, 0x0d, 0xb6, 0x77, 0x94, 0x71, 0xeb, 0xf5, 0xf9, 0x14, 0x9e, 0x63, 0x4d, 0x82, 0xce,
    0x4e, 0x20, 0xef, 0x53, 0x91, 0x73, 0xec, 0x83, 0xc3, 0xad, 0x18, 0x07, 0x59, 0xcc, 0xbe, 0xae,
    0xcc, 0x54, 0x36, 0x8f, 0xa9, 0xa1, 0x3b, 0xd6, 0x19, 0x68, 0x62, 0x8a, 0xd4, 0xaf, 0x60, 0xa1,
    0xcf, 0x78, 0x8b, 0xad, 0x65, 0xf1, 0xf8, 0xc7, 0xbd, 0xe5, 0x92, 0xcc, 0xf5, 0x59, 0x1a, 0xa4,
    0x4e, 0xf3, 0x80, 0x39, 0x42, 0xed, 0x2f, 0x4b, 0xbe, 0x0d, 0xeb, 0x83, 0x6c, 0xa6, 0xfe, 0xf1,
    0x06, 0xa6, 0xa8, 0xa5, 0xaa, 0xc5, 0xbd, 0xa2, 0x8b, 0x52, 0xdb, 0x5d, 0x8e, 0x2a, 0xa5, 0x93,
    0xa7, 0x8a, 0xf8, 0xd0, 0x5e, 0x4c, 0x03, 0x7b, 0x3a, 0xb9, 0xc6, 0xac, 0x25, 0xaf, 0xb6, 0xa6,
    0xe6, 0x3f, 0xd6, 0x4a, 0xb8, 0xe5, 0x13, 0xa9, 0xde, 0xff, 0x6c, 0x6e, 0xd7, 0x8f, 0xba, 0x4c,
    0x53, 0xf2, 0x63, 0x80, 0x7a, 0xa0, 0x83, 0xe5, 0x83, 0xc6, 0xbc, 0x17, 0xd0, 0x5e, 0x2e, 0x2f,
    0x6e, 0xcd, 0x62, 0x7f, 0xec, 0xb9, 0xf5, 0xbf, 0xb8, 0x74, 0x68, 0x2d, 0xb4, 0xac, 0x13, 0x7d,
    0xb2, 0xe5, 0xf1, 0x2f, 0x3d, 0xc8, 0xaa, 0xdc, 0xa2, 0x39, 0x7e, 0xdb, 0x11, 0x33, 0xf8, 0x96,
    0xee, 0xab, 0xcd, 0xbd, 0xd8, 0xa2, 0x5c, 0xf8, 0x53, 0xb9, 0x26, 0xe5, 0x3e, 0x94, 0xe5, 0x65,
    0xb1, 0x3a, 0xb1, 0xf0, 0x4a, 0x3a, 0x52, 0x6d, 0x37, 0x13, 0x61, 0x31, 0x5d, 0x36, 0x1e, 0xaf,
    0x40, 0x5b, 0x7e, 0x23, 0xbb, 0xf7, 0xd2, 0xe7, 0x80, 0x25, 0xe9, 0x9e, 0xb9, 0x67, 0xef, 0x78,
    0x82, 0xb9, 0x4a, 0xeb, 0x3a, 0xad, 0xa4, 0x98, 0xa9, 0x1d, 0x64, 0xb6, 0xe7, 0x04, 0x4f, 0x00,
    0xdd, 0x76, 0x2d, 0x68, 0xd4, 0x02, 0xda, 0x8b, 0x99, 0xe7, 0x5a, 0x1a, 0x7e, 0x61, 0xd8, 0xf1,
    0xa3, 0xac, 0x77, 0xd9, 0x48, 0x1b, 0x72, 0xef, 0xf3, 0x38, 0x1f, 0xdd, 0x37, 0x2f, 0x13, 0xad,
    0xe5, 0xc3, 0x1f, 0x58, 0x50, 0xc4, 0xc2, 0xab, 0xcb, 0x53, 0x78, 0x96, 0xda, 0xca, 0x73, 0x22,
    0xe6, 0xe2, 0x06, 0x40, 0x01, 0x95, 0xf5]:
  #[0xdc, 0x04, 0x47, 0x14, 0x59, 0xac, 0x57, 0x84, 0xca, 0xfc, 0x4a, 0x74, 0x76, 0x1b, 0x83, 0xca],
}
